package com.yanqu.xiuxian.gameserver.tripletown.logic;

import com.yanqu.xiuxian.gameserver.tripletown.config.*;
import com.yanqu.xiuxian.gameserver.tripletown.data.IUserData;
import com.yanqu.xiuxian.gameserver.tripletown.entity.*;
import com.yanqu.xiuxian.server.protocol.GameErrorCode;
import com.yanqu.xiuxian.utils.RandomHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 三消-逻辑
 */
public class EliminateLogic {

    public static final Logger logger = LogManager.getLogger(EliminateLogic.class.getName());

    /**
     * 消除
     *
     * @param fromX 从这里
     * @param toX   跟这里交换
     */
    public static EliminateResult eliminateBlock(IConfig config, IUserData userData, int multi, int fromX, int fromY, int toX, int toY) {
        EliminateResult eliminateResult = new EliminateResult(); // 最终结果
        // 【校验】
        if (!BlockLogic.validExchange(fromX, fromY, toX, toY)) {
            eliminateResult.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return eliminateResult;
        }
        int[][] copyBlockList = BlockLogic.copy(userData.getBlockList(multi)); // 复制的全部格子
        if (!BlockLogic.validExisted(copyBlockList, fromX, fromY, toX, toY)) {
            eliminateResult.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return eliminateResult;
        }

        Random random = new Random();
        int guideIndex = userData.getGuideIndex(); // 引导下标

        Map<Integer, Map<Integer, Block>> dropMap = new ConcurrentHashMap<>(); // 上一轮掉落的方块
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            dropMap.put(tmpY, new ConcurrentHashMap<>());
        }

        // 【交换】
        BlockLogic.exchange(copyBlockList, fromX, fromY, toX, toY);

        // 【订单】
        Order copyOrder = OrderLogic.copy(userData.getOrder(multi)); // 复制的订单
        if (copyOrder != null) {
            copyOrder.addStep(1);
        }

        // 【循环处理每轮数据】
        for (int round = 1; round <= 100; round++) {
            EliminateRoundResult roundResult = new EliminateRoundResult(); // 每轮结果
            Map<Integer, Map<Integer, Block>> eliminateMap = new ConcurrentHashMap<>(); // 记录消除的格子
            for (int y = 0; y < copyBlockList.length; y++) {
                eliminateMap.put(y, new ConcurrentHashMap<>());
            }

            // 【分阶段标记消除的方块】
            if (round == 1) { // 首轮有炸弹连环爆炸，有多阶段
                List<Block> waitBombBlockList = new ArrayList<>();
                for (int stage = 1; stage <= 100; stage++) { // 假装是while
                    EliminateStageResult eliminateStageResult = new EliminateStageResult();
                    if (stage == 1) {
                        BombLogic.handleBomb(copyBlockList, eliminateMap, fromX, fromY, toX, toY, eliminateStageResult, waitBombBlockList); // 首次炸弹
                        handleEliminateX(copyBlockList, eliminateMap, eliminateStageResult); // 横向
                        handleEliminateY(copyBlockList, eliminateMap, eliminateStageResult); // 纵向
                    } else {
                        waitBombBlockList = BombLogic.handleBombExploded(copyBlockList, eliminateMap, eliminateStageResult, waitBombBlockList); // 其他次炸弹
                    }
                    roundResult.addEliminateStageResult(eliminateStageResult);
                    // 判断连环炸弹全部爆炸完
                    if (waitBombBlockList.isEmpty()) {
                        break;
                    }
                }
            } else { // 其他轮只有消除，一阶段
                EliminateStageResult eliminateStageResult = new EliminateStageResult();
                handleEliminateX(copyBlockList, eliminateMap, eliminateStageResult); // 横向
                handleEliminateY(copyBlockList, eliminateMap, eliminateStageResult); // 纵向
                roundResult.addEliminateStageResult(eliminateStageResult);
            }

            // 【判断是否结束】
            if (!hadEliminate(eliminateMap)) {
                if (round == 1) {
                    eliminateResult.setRet(GameErrorCode.E__NO_BLOCK_TO_ELIMINATE);
                    return eliminateResult;
                } else {
                    break; // 如果没失败，后续还有操作，不能return
                }
            }

            // 【消除方块】
            setEliminateEmpty(copyBlockList, round, multi, eliminateMap, config);

            // 【加炸弹】
            BombLogic.addBomb(fromX, fromY, toX, toY, round, eliminateMap, dropMap, copyBlockList, roundResult);

            // 【订单】
            if (copyOrder != null) {

                // 【加订单进度】
                OrderLogic.addOrderProg(copyOrder, eliminateMap);

                // 【设置当前订单】
                roundResult.setCurOrder(OrderLogic.copy(copyOrder));
            }

            // 【填充方块】
            dropMap = new ConcurrentHashMap<>(); // 记录掉落方块
            for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
                dropMap.put(tmpY, new ConcurrentHashMap<>());
            }
            dropOldBlock(copyBlockList, dropMap); //旧方块掉落
            guideIndex = dropNewBlock(multi, guideIndex, copyBlockList, dropMap, config); // 添加新方块

            // 【添加本轮结果】
            roundResult.setBlockList(BlockLogic.copy(copyBlockList));
            eliminateResult.addEliminateRoundResult(roundResult);

            // 【判断死局】
            if (!calEliminateTips(copyBlockList).isSuccess()) {
                for (int i = 0; i < 10; i++) { // 重排到可以消除才结束
                    rearrange(copyBlockList);
                    if (calEliminateTips(copyBlockList).isSuccess()) {
                        break;
                    }
                }
                // 【添加重排结果】
                EliminateRoundResult tmpRoundResult = new EliminateRoundResult();
                tmpRoundResult.setBlockList(BlockLogic.copy(copyBlockList));
                tmpRoundResult.setType(2); // 1正常消除，2重排
                // 【订单】
                if (copyOrder != null) {
                    tmpRoundResult.setCurOrder(OrderLogic.copy(copyOrder));
                }
                eliminateResult.addEliminateRoundResult(tmpRoundResult);
            }
        }

        // 【处理订单】
        OrderLogic.handleOrder(config, userData, multi, random, eliminateResult, copyBlockList, copyOrder);

        // 【最终数据】
        eliminateResult.setGuideIndex(guideIndex);

        return eliminateResult;
    }

    public static EliminateResult eliminateColor(IConfig config, IUserData userData, int multi, int fromX, int fromY) {
        EliminateResult eliminateResult = new EliminateResult(); // 最终结果
        // 【校验】
        int[][] copyBlockList = BlockLogic.copy(userData.getBlockList(multi)); // 复制的全部格子
        if (!BlockLogic.existed(copyBlockList, fromX, fromY)) {
            eliminateResult.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return eliminateResult;
        }

        Random random = new Random();
        int guideIndex = userData.getGuideIndex(); // 引导下标

        Map<Integer, Map<Integer, Block>> dropMap = new ConcurrentHashMap<>(); // 上一轮掉落的方块
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            dropMap.put(tmpY, new ConcurrentHashMap<>());
        }

        // 【订单】
        Order copyOrder = OrderLogic.copy(userData.getOrder(multi)); // 复制的订单

        // 【循环处理每轮数据】
        for (int round = 1; round <= 100; round++) {
            EliminateRoundResult roundResult = new EliminateRoundResult(); // 每轮结果
            Map<Integer, Map<Integer, Block>> eliminateMap = new ConcurrentHashMap<>(); // 记录消除的格子
            for (int y = 0; y < copyBlockList.length; y++) {
                eliminateMap.put(y, new ConcurrentHashMap<>());
            }

            EliminateStageResult eliminateStageResult = new EliminateStageResult();
            if (round == 1) {
                List<Block> calColorList = BlockLogic.calColorList(copyBlockList, fromX, fromY);
                if (BlockLogic.isBomb(copyBlockList[fromY][fromX])) {
                    for (Block block : calColorList) {
                        List<Block> bombEliminateList = BombLogic.calBombEliminateList(copyBlockList, block);
                        for (Block bombBlock : bombEliminateList) {
                            // 记录消除的格子
                            if (!eliminateMap.get(bombBlock.getY()).containsKey(bombBlock.getX())) {
                                eliminateMap.get(bombBlock.getY()).put(bombBlock.getX(), bombBlock);
                                // 记录阶段数据
                                eliminateStageResult.addBlock(bombBlock);
                            }
                        }
                    }
                } else {
                    for (Block block : calColorList) {
                        // 记录消除的格子
                        if (!eliminateMap.get(block.getY()).containsKey(block.getX())) {
                            eliminateMap.get(block.getY()).put(block.getX(), block);
                            // 记录阶段数据
                            eliminateStageResult.addBlock(block);
                        }
                    }
                }
            }
            handleEliminateX(copyBlockList, eliminateMap, eliminateStageResult); // 横向
            handleEliminateY(copyBlockList, eliminateMap, eliminateStageResult); // 纵向
            roundResult.addEliminateStageResult(eliminateStageResult);

            // 【判断是否结束】
            if (!hadEliminate(eliminateMap)) {
                if (round == 1) {
                    eliminateResult.setRet(GameErrorCode.E__NO_BLOCK_TO_ELIMINATE);
                    return eliminateResult;
                } else {
                    break; // 如果没失败，后续还有操作，不能return
                }
            }

            // 【消除方块】
            setEliminateEmpty(copyBlockList, round, multi, eliminateMap, config);

            // 【加炸弹】
            BombLogic.addBomb(fromX, fromY, round, eliminateMap, dropMap, copyBlockList, roundResult);

            // 【订单】
            if (copyOrder != null) {

                // 【加订单进度】
                OrderLogic.addOrderProg(copyOrder, eliminateMap);

                // 【设置当前订单】
                roundResult.setCurOrder(OrderLogic.copy(copyOrder));
            }

            // 【填充方块】
            dropMap = new ConcurrentHashMap<>(); // 记录掉落方块
            for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
                dropMap.put(tmpY, new ConcurrentHashMap<>());
            }
            dropOldBlock(copyBlockList, dropMap); //旧方块掉落
            guideIndex = dropNewBlock(multi, guideIndex, copyBlockList, dropMap, config); // 添加新方块

            // 【添加本轮结果】
            roundResult.setBlockList(BlockLogic.copy(copyBlockList));
            eliminateResult.addEliminateRoundResult(roundResult);

            // 【判断死局】
            if (!calEliminateTips(copyBlockList).isSuccess()) {
                for (int i = 0; i < 10; i++) { // 重排到可以消除才结束
                    rearrange(copyBlockList);
                    if (calEliminateTips(copyBlockList).isSuccess()) {
                        break;
                    }
                }
                // 【添加重排结果】
                EliminateRoundResult tmpRoundResult = new EliminateRoundResult();
                tmpRoundResult.setBlockList(BlockLogic.copy(copyBlockList));
                tmpRoundResult.setType(2); // 1正常消除，2重排
                // 【订单】
                if (copyOrder != null) {
                    tmpRoundResult.setCurOrder(OrderLogic.copy(copyOrder));
                }
                eliminateResult.addEliminateRoundResult(tmpRoundResult);
            }
        }

        // 【处理订单】
        OrderLogic.handleOrder(config, userData, multi, random, eliminateResult, copyBlockList, copyOrder);

        // 【最终数据】
        eliminateResult.setGuideIndex(guideIndex);

        return eliminateResult;
    }

    public static EliminateResult eliminateMostColor(IConfig config, IUserData userData, int multi) {
        EliminateResult eliminateResult = new EliminateResult(); // 最终结果
        // 【校验】
        int[][] copyBlockList = BlockLogic.copy(userData.getBlockList(multi)); // 复制的全部格子
        int mostColor = BlockLogic.getMostColor(copyBlockList);
        if (mostColor == 0) {
            eliminateResult.setRet(GameErrorCode.E_DATA_ERROR);
            return eliminateResult;
        }
        Block firstColorBlock = BlockLogic.getFirstColorBlock(copyBlockList, mostColor);
        if (firstColorBlock == null) {
            eliminateResult.setRet(GameErrorCode.E_DATA_ERROR);
            return eliminateResult;
        }

        eliminateResult = eliminateColor(config, userData, multi, firstColorBlock.getX(), firstColorBlock.getY());
        return eliminateResult;
    }

    public static EliminateResult eliminateBomb(IConfig config, IUserData userData, int multi, int fromX, int fromY) {
        EliminateResult eliminateResult = new EliminateResult(); // 最终结果
        // 【校验】
        int[][] copyBlockList = BlockLogic.copy(userData.getBlockList(multi)); // 复制的全部格子
        if (!BlockLogic.existed(copyBlockList, fromX, fromY)) {
            eliminateResult.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return eliminateResult;
        }
        if (!BlockLogic.isBomb(copyBlockList[fromY][fromX])) {
            eliminateResult.setRet(GameErrorCode.E_REQUEST_ARGUMENT_ERROR);
            return eliminateResult;
        }

        Random random = new Random();
        int guideIndex = userData.getGuideIndex(); // 引导下标

        Map<Integer, Map<Integer, Block>> dropMap = new ConcurrentHashMap<>(); // 上一轮掉落的方块
        for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
            dropMap.put(tmpY, new ConcurrentHashMap<>());
        }

        // 【订单】
        Order copyOrder = OrderLogic.copy(userData.getOrder(multi)); // 复制的订单
        if (copyOrder != null) {
            copyOrder.addStep(1);
        }

        // 【循环处理每轮数据】
        for (int round = 1; round <= 100; round++) {
            EliminateRoundResult roundResult = new EliminateRoundResult(); // 每轮结果
            Map<Integer, Map<Integer, Block>> eliminateMap = new ConcurrentHashMap<>(); // 记录消除的格子
            for (int y = 0; y < copyBlockList.length; y++) {
                eliminateMap.put(y, new ConcurrentHashMap<>());
            }

            // 【分阶段标记消除的方块】
            if (round == 1) { // 首轮有炸弹连环爆炸，有多阶段
                List<Block> waitBombBlockList = new ArrayList<>();
                for (int stage = 1; stage <= 100; stage++) { // 假装是while
                    EliminateStageResult eliminateStageResult = new EliminateStageResult();
                    if (stage == 1) {
                        BombLogic.handleBomb(copyBlockList, eliminateMap, fromX, fromY, eliminateStageResult, waitBombBlockList); // 首次炸弹
                        handleEliminateX(copyBlockList, eliminateMap, eliminateStageResult); // 横向
                        handleEliminateY(copyBlockList, eliminateMap, eliminateStageResult); // 纵向
                    } else {
                        waitBombBlockList = BombLogic.handleBombExploded(copyBlockList, eliminateMap, eliminateStageResult, waitBombBlockList); // 其他次炸弹
                    }
                    roundResult.addEliminateStageResult(eliminateStageResult);
                    // 判断连环炸弹全部爆炸完
                    if (waitBombBlockList.isEmpty()) {
                        break;
                    }
                }
            } else { // 其他轮只有消除，一阶段
                EliminateStageResult eliminateStageResult = new EliminateStageResult();
                handleEliminateX(copyBlockList, eliminateMap, eliminateStageResult); // 横向
                handleEliminateY(copyBlockList, eliminateMap, eliminateStageResult); // 纵向
                roundResult.addEliminateStageResult(eliminateStageResult);
            }

            // 【判断是否结束】
            if (!hadEliminate(eliminateMap)) {
                if (round == 1) {
                    eliminateResult.setRet(GameErrorCode.E__NO_BLOCK_TO_ELIMINATE);
                    return eliminateResult;
                } else {
                    break; // 如果没失败，后续还有操作，不能return
                }
            }

            // 【消除方块】
            setEliminateEmpty(copyBlockList, round, multi, eliminateMap, config);

            // 【加炸弹】
            BombLogic.addBomb(fromX, fromY, round, eliminateMap, dropMap, copyBlockList, roundResult);

            // 【订单】
            if (copyOrder != null) {

                // 【加订单进度】
                OrderLogic.addOrderProg(copyOrder, eliminateMap);

                // 【设置当前订单】
                roundResult.setCurOrder(OrderLogic.copy(copyOrder));
            }

            // 【填充方块】
            dropMap = new ConcurrentHashMap<>(); // 记录掉落方块
            for (int tmpY = 0; tmpY < copyBlockList.length; tmpY++) {
                dropMap.put(tmpY, new ConcurrentHashMap<>());
            }
            dropOldBlock(copyBlockList, dropMap); //旧方块掉落
            guideIndex = dropNewBlock(multi, guideIndex, copyBlockList, dropMap, config); // 添加新方块

            // 【添加本轮结果】
            roundResult.setBlockList(BlockLogic.copy(copyBlockList));
            eliminateResult.addEliminateRoundResult(roundResult);

            // 【判断死局】
            if (!calEliminateTips(copyBlockList).isSuccess()) {
                for (int i = 0; i < 10; i++) { // 重排到可以消除才结束
                    rearrange(copyBlockList);
                    if (calEliminateTips(copyBlockList).isSuccess()) {
                        break;
                    }
                }
                // 【添加重排结果】
                EliminateRoundResult tmpRoundResult = new EliminateRoundResult();
                tmpRoundResult.setBlockList(BlockLogic.copy(copyBlockList));
                tmpRoundResult.setType(2); // 1正常消除，2重排
                // 【订单】
                if (copyOrder != null) {
                    tmpRoundResult.setCurOrder(OrderLogic.copy(copyOrder));
                }
                eliminateResult.addEliminateRoundResult(tmpRoundResult);
            }
        }

        // 【处理订单】
        OrderLogic.handleOrder(config, userData, multi, random, eliminateResult, copyBlockList, copyOrder);

        // 【最终数据】
        eliminateResult.setGuideIndex(guideIndex);

        return eliminateResult;
    }

    /**
     * 掉落新格子
     */
    private static int dropNewBlock(int multi, int guideIndex, int[][] copyBlockList, Map<Integer, Map<Integer, Block>> dropMap, IConfig config) {
        // 计算权重
        Map<Integer, Integer> countMap = new ConcurrentHashMap<>();
        int startNum = multi == 16 ? 11 : multi == 8 ? 5 : 1;
        for (int i = 0; i <= 3; i++) {
            countMap.put(startNum + i, 0);
        }
        for (int y = 0; y < copyBlockList.length; y++) {
            for (int x = 0; x < copyBlockList[y].length; x++) {
                if (countMap.containsKey(copyBlockList[y][x])) {
                    countMap.put(copyBlockList[y][x], countMap.get(copyBlockList[y][x]) + 1);
                }
            }
        }
        List<Integer> colorList = new ArrayList<>();
        List<Integer> countList = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            colorList.add(entry.getKey());
            countList.add(entry.getValue());
        }
        for (int i = 0; i < colorList.size() - 1; i++) {
            for (int j = i + 1; j < colorList.size(); j++) {
                if (countList.get(i) < countList.get(j)) {
                    int tmpColor = colorList.get(i);
                    colorList.set(i, colorList.get(j));
                    colorList.set(j, tmpColor);
                    int tmpCount = countList.get(i);
                    countList.set(i, countList.get(j));
                    countList.set(j, tmpCount);
                }
            }
        }
        int count = -1;
        int rank = -1;
        List<Integer> weightList = new ArrayList<>();
        for (int i = 0; i < colorList.size(); i++) {
            if (count != countList.get(i)) {
                rank++;
                count = countList.get(i);
            }
            int baseWeight = config.getBlockConfigMap().get(colorList.get(i)).getWeight();
            weightList.add(baseWeight + config.getBlockWeightList().get(rank));
        }

        // 获取引导格子
        int[] initBlock = config.getInitBlock();
        // 生成新格子
        Random random = new Random();
        for (int y = 0; y < copyBlockList.length; y++) {
            for (int x = 0; x < copyBlockList[y].length; x++) {
                if (copyBlockList[y][x] == 0) {
                    int block = multi == 1 && guideIndex < initBlock.length ?
                            initBlock[guideIndex++] : calNextBlock(colorList, weightList, random);
                    copyBlockList[y][x] = block;
                    dropMap.get(y).put(x, new Block(x, y, block));
                }
            }
        }
        return guideIndex;
    }

    /**
     * 旧方块掉落
     */
    private static void dropOldBlock(int[][] copyBlockList, Map<Integer, Map<Integer, Block>> dropMap) {
        for (int y = 0; y < copyBlockList.length; y++) {
            for (int x = 0; x < copyBlockList[y].length; x++) {
                if (copyBlockList[y][x] == 0) {
                    int index = -1;
                    for (int tmpY = y + 1; tmpY < copyBlockList.length; tmpY++) {
                        if (copyBlockList[tmpY][x] != 0) {
                            index = tmpY;
                            break;
                        }
                    }
                    if (index != -1) {
                        copyBlockList[y][x] = copyBlockList[index][x];
                        copyBlockList[index][x] = 0;
                        dropMap.get(y).put(x, new Block(x, y, copyBlockList[y][x]));
                    }
                }
            }
        }
    }

    /**
     * 是否有消除
     */
    private static boolean hadEliminate(Map<Integer, Map<Integer, Block>> eliminateMap) {
        for (Map<Integer, Block> blockMap : eliminateMap.values()) {
            if (!blockMap.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取下一个格子
     */
    private static int calNextBlock(List<Integer> colorList, List<Integer> weightList, Random random) {
        int index = RandomHelper.getRandomIndexByWeight(weightList, random);
        return colorList.get(index);
    }

    /**
     * 消除的方块清空
     */
    private static void setEliminateEmpty(int[][] copyBlockList, int round, int multi, Map<Integer, Map<Integer, Block>> eliminateMap, IConfig config) {
        long blockScore = calBlockScore(round, multi, config);
        for (Map<Integer, Block> blockMap : eliminateMap.values()) {
            for (Block block : blockMap.values()) {
                copyBlockList[block.getY()][block.getX()] = 0;
                // 记录本轮结果
                block.setScore(blockScore);
            }
        }
    }

    /**
     * 处理横向消除
     */
    private static void handleEliminateY(int[][] copyBlockList, Map<Integer, Map<Integer, Block>> eliminateMap, EliminateStageResult eliminateStageResult) {
        for (int x = 0; x < copyBlockList[0].length; x++) {
            for (int y = 0; y < copyBlockList.length - 2; y++) {
                // 不是炸弹 且 能消除
                if (!BlockLogic.isBomb(copyBlockList[y][x]) && copyBlockList[y][x] == copyBlockList[y + 1][x] && copyBlockList[y][x] == copyBlockList[y + 2][x]) {
                    int size = 0;
                    for (int tmpY = y; tmpY < copyBlockList.length; tmpY++) {
                        if (copyBlockList[tmpY][x] == copyBlockList[y][x]) {
                            size++;
                            if (!eliminateMap.get(tmpY).containsKey(x)) {
                                Block block = new Block(x, tmpY, copyBlockList[tmpY][x]);
                                eliminateMap.get(tmpY).put(x, block);
                                eliminateStageResult.addBlock(block);
                            }
                            eliminateMap.get(tmpY).get(x).setEliminate(true);
                        } else break;
                    }
                    y += size - 1;
                }
            }
        }
    }

    /**
     * 处理横向消除
     */
    private static void handleEliminateX(int[][] copyBlockList, Map<Integer, Map<Integer, Block>> eliminateMap, EliminateStageResult eliminateStageResult) {
        for (int y = 0; y < copyBlockList.length; y++) {
            for (int x = 0; x < copyBlockList[y].length - 2; x++) {
                // 不是炸弹 且 能消除
                if (!BlockLogic.isBomb(copyBlockList[y][x]) && copyBlockList[y][x] == copyBlockList[y][x + 1] && copyBlockList[y][x] == copyBlockList[y][x + 2]) {
                    int size = 0;
                    for (int tmpX = x; tmpX < copyBlockList[y].length; tmpX++) {
                        if (copyBlockList[y][tmpX] == copyBlockList[y][x]) {
                            size++;
                            if (!eliminateMap.get(y).containsKey(tmpX)) {
                                Block block = new Block(tmpX, y, copyBlockList[y][x]);
                                eliminateMap.get(block.getY()).put(block.getX(), block);
                                eliminateStageResult.addBlock(block);
                            }
                            eliminateMap.get(y).get(tmpX).setEliminate(true);
                        } else {
                            break;
                        }
                    }
                    x += size - 1;
                }
            }
        }
    }

    /**
     * 获取消除提示
     */
    public static EliminateTips calEliminateTips(int[][] blockList) {
        EliminateTips eliminateTips = new EliminateTips();

        // 先判断炸弹
        for (int y = 0; y < blockList.length; y++) {
            for (int x = 0; x < blockList[y].length; x++) {
                if (BlockLogic.isBomb(blockList[y][x])) {
                    eliminateTips.setFromBlock(new Block(x, y, blockList[y][x]));
                    return eliminateTips;
                }
            }
        }

        // 判断消除
        int[][] copyBlockList = BlockLogic.copy(blockList);
        for (int y = 0; y < blockList.length; y++) {
            for (int x = 0; x < blockList[y].length; x++) {
                // 向右交换
                if (tryExchange(blockList, eliminateTips, copyBlockList, x, y, x + 1, y)) {
                    return eliminateTips;
                }
                // 向左交换
                if (tryExchange(blockList, eliminateTips, copyBlockList, x, y, x - 1, y)) {
                    return eliminateTips;
                }
                // 向上交换
                if (tryExchange(blockList, eliminateTips, copyBlockList, x, y, x, y + 1)) {
                    return eliminateTips;
                }
                // 向下交换
                if (tryExchange(blockList, eliminateTips, copyBlockList, x, y, x, y - 1)) {
                    return eliminateTips;
                }
            }
        }
        eliminateTips.setSuccess(false);
        return eliminateTips;
    }

    /**
     * 尝试交换
     */
    private static boolean tryExchange(int[][] blockList, EliminateTips eliminateTips, int[][] copyBlockList, int fromX, int fromY, int toX, int toY) {
        List<Block> eliminateList;
        if (BlockLogic.existed(copyBlockList, fromX, fromY) && BlockLogic.existed(copyBlockList, toX, toY)) {
            BlockLogic.exchange(copyBlockList, fromX, fromY, toX, toY);
            eliminateList = getEliminateList(copyBlockList, toX, toY);
            BlockLogic.exchange(copyBlockList, fromX, fromY, toX, toY);
            if (eliminateList.size() >= 2) {
                for (Block block : eliminateList) {
                    if (block.getX() == fromX && block.getY() == fromY) {
                        eliminateList.remove(block);
                        break;
                    }
                }
                eliminateTips.setBlockList(eliminateList);
                eliminateTips.setFromBlock(new Block(fromX, fromY, blockList[fromY][fromX]));
                eliminateTips.setToBlock(new Block(toX, toY, blockList[toY][toX]));
                return true;
            }
        }
        return false;
    }

    /**
     * 获取该点一起消除的List（不含该点）
     */
    private static List<Block> getEliminateList(int[][] copyBlockList, int stopX, int stopY) {
        List<Block> xList = new ArrayList<>();
        List<Block> yList = new ArrayList<>();
        for (int tmpX = stopX + 1; tmpX < copyBlockList[0].length; tmpX++) {
            if (copyBlockList[stopY][tmpX] == copyBlockList[stopY][stopX]) {
                xList.add(new Block(tmpX, stopY, copyBlockList[stopY][tmpX]));
            } else {
                break;
            }
        }
        for (int tmpX = stopX - 1; tmpX >= 0; tmpX--) {
            if (copyBlockList[stopY][tmpX] == copyBlockList[stopY][stopX]) {
                xList.add(new Block(tmpX, stopY, copyBlockList[stopY][tmpX]));
            } else {
                break;
            }
        }
        for (int tmpY = stopY + 1; tmpY < copyBlockList.length; tmpY++) {
            if (copyBlockList[tmpY][stopX] == copyBlockList[stopY][stopX]) {
                yList.add(new Block(stopX, tmpY, copyBlockList[tmpY][stopX]));
            } else {
                break;
            }
        }
        for (int tmpY = stopY - 1; tmpY >= 0; tmpY--) {
            if (copyBlockList[tmpY][stopX] == copyBlockList[stopY][stopX]) {
                yList.add(new Block(stopX, tmpY, copyBlockList[tmpY][stopX]));
            } else {
                break;
            }
        }
        if (xList.size() < 2 && yList.size() < 2) {
            return new ArrayList<>();
        } else if (xList.size() >= 2 && yList.size() >= 2) {
            xList.addAll(yList);
            return xList;
        } else {
            return xList.size() >= 2 ? xList : yList;
        }
    }

    /**
     * 重排
     */
    public static void rearrange(int[][] blockList) {
        List<Integer> list = new ArrayList<>();
        for (int y = 0; y < blockList.length; y++) {
            for (int x = 0; x < blockList[y].length; x++) {
                list.add(blockList[y][x]);
            }
        }
        Random random = new Random();
        for (int y = 0; y < blockList.length; y++) {
            for (int x = 0; x < blockList[y].length; x++) {
                int index = random.nextInt(list.size());
                blockList[y][x] = list.get(index);
                list.remove(index);
            }
        }
    }

    /**
     * 计算第x轮的格子积分（x从1开始）
     */
    public static long calBlockScore(int round, int multi, IConfig config) {
        // 基础积分
        BigDecimal baseScore = BigDecimal.valueOf(config.getEliminateScoreList().get(multi == 16 ? 2 : multi == 8 ? 1 : 0));
        // 放大倍数
        int score;
        Map<Integer, ? extends IScoreConfig> scoreConfigMap = config.getScoreConfigMap();
        if (scoreConfigMap.containsKey(round)) {
            score = scoreConfigMap.get(round).getScore();
        } else {
            // 没有配置的话，就取最大值
            int maxRound = -1;
            for (IScoreConfig scoreConfig : scoreConfigMap.values()) {
                if (scoreConfig.getContinuousNum() > maxRound) maxRound = scoreConfig.getContinuousNum();
            }
            score = scoreConfigMap.get(maxRound).getScore();
        }
        // 结果
        return baseScore.multiply(BigDecimal.valueOf(1000 + score)).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
    }

}
